/// 这个是类 
{
   class Person {
      name: string
      age: number
   }

   let man = new Person
   man.name = '老师'
   man.age = 30

   console.log(man, 'man')
}


// static静态    readonly一旦声明就不能修改
{
   // 这个被static 声明后 就属于他这个类   就不属于他这个实例化了 
   class Animal {
      //  static    list = '修狗'
      static readonly list = '修狗'
      fun() {
         console.log('说了什么')
      }
   }
   console.log(Animal.list, 'animal')
}


// Ts  类的继承
{
   class Animal { //父类
      name: string
      sleep() {
         console.log(this.name + "睡觉")
      }

      constructor(name: string) {
         this.name = name
      }
   }

   class Dog extends Animal {  //子类继承父类
      hobbit() {
         console.log(this.name + '继承了hobbit方法')
      }
   }

   let jm = new Dog('金毛')
   jm.hobbit()
   console.log(jm.name)
}


// Ts 的重写  这个方法重写  子类和父类的方法名相同的时候就会重写
{
   class Animal {
      name: string = "动物"
      sleep() {
         console.log('动物在睡觉')
      }
   }

   class Dog extends Animal {
      name: string = "狗1"
      sleep() {
         console.log('狗在睡觉')
      }
   }

   let jm = new Dog()
   console.log(jm.name)
   jm.sleep()   //重新把sleep方法重写
}


// TS  super 关键字  重写
{
   class Animal {
      name: string
      sleep() {
         console.log('狗在睡觉')
      }
      constructor(name: string) {
         this.name = name
      }
   }

   class Dog extends Animal {
      age: number
      sleep() {
         // super  代表父类  父类->  超类
         super.sleep()
      }

      constructor(name: string, age: number) {
         super(name)//超类初始化  父类的是实例
         this.age = age
      }
   }

   let jm = new Dog('金毛', 123)
   // jm.sleep()
   console.log(jm)

}


// TS  中的抽象类
{
   // 抽象方法特点
   // 1：没有方法体  没有实现
   abstract class Animal {
      name: string = "抽象类"
      abstract sleep(): void
   }
   // 1 : 抽象类只能被继承 不能 初始化一个实例
   // class Dog extends Animal {
   //    sleep() { }
   // }

   // 2 : 子类继承抽象类，必须重写抽象类中所有抽象方法  如果不重写  那么这个类也应该是一个抽象类
   abstract class Dog extends Animal {
      abstract bark(): void
   }

   class JM extends Dog {
      sleep() { }
      bark() { }
   }

}

// TS  中的接口 implements 形式  好用
{

   // 第一种以对象的方式
   interface myInterface {
      name: string
      age: number
      sleep(): void  //void 没有返回值
   }

   let b: myInterface
   b = {
      name: '123',
      age: 123,
      sleep() {
         console.log("myInterface")
      }
   }
   console.log(b.name)
   b.sleep()


   // -------------第二种以方法的方式-----------------------
   class Person implements myInterface {
      name: string;
      age: number;
      constructor(name, age) {
         this.name = name
         this.age = age
      }
      sleep() {
         console.log(this.name)
      }
   }

   const god = new Person('铁子', 56)
   god.sleep()  //'调用Person里面的方法'
   console.log(god, 'god')
}


// TS  中的  属性封装
// public  修饰的属性可以任意访问
// private 私有属性 你
// protected  受保护的属性
{
   //  -------------------------------------------------- public  修饰的属性可以任意访问
   // class Person {
   //    name: string
   //    constructor(name: string) {
   //       this.name = name
   //    }
   // }

   // let obj = new Person('小明')

   // obj.name = '小明'
   // console.log(obj.name, 'public')

   // -------------------------------------------------- private 私有属性 
   // class Person {
   //    private name: string
   //    constructor(name: string) {
   //       this.name = name
   //    }

   //    getName() {
   //       return this.name
   //    }
   // }

   // let obj = new Person('小明')
   // console.log(obj.getName(), 'private')

   //-------------------------------------------------protected 受保护的属性
   // class Person {
   //    protected name: string
   //    constructor(name: string) {
   //       this.name = name
   //    }

   //    protected getName() {
   //       return this.name
   //    }
   // }

   // // 继承的时候要用super 超类去指定父类的方法
   // class Docker extends Person {
   //    getName() {
   //       return super.getName()
   //    }
   // }

   // let obj = new Docker('小明')
   // console.log(obj.getName())


   // --------------------------------------   属性封装
   //    class Person {
   //       private name:string;
   //       private age:number;
   //       constructor(name:string,age:number){
   //           this.name=name;
   //           this.age=age;
   //       }
   //   }

   //--------------------------------get和set语法糖--------属性存取器
   class Person {
      private name: string
      private age: number
      constructor(name: string, age: number) {
         this.name = name;
         this.age = age;
      }

      get getName(): string {
         return this.name
      }

      set setName(name: string) {
         if (name === '小明') this.name = name
      }

   }
   let obj = new Person('小1', 26)
   obj.setName = '小3'
   console.log(obj, 'obj123123')

}


// TS  中 泛型
{
   // 不知道返回的什么类型就可以用到泛型
   // 泛型要用大写来表示  任意大写字母
   // function cache<T>(prop: T): T {
   //    return prop
   // }

   // let a = cache<string>("true")  //泛型的约束   只能是字符串

   // ---------------------------------使用多个泛型
   // function cache<Ta, Pa>(prop: Ta, falg: Pa): Ta {
   //    return prop
   // }

   // let a = cache<string, number>("true", 123)   //多个泛型约束



   // ------------------------------------------------------------------interface 接口泛型的使用
   interface myInterface<T> {
      name: T
   }


   class Person<T, P> implements myInterface<T>{
      name
      age
      constructor(name, age) {
         this.name = name
         this.age = age
      }
   }

   let obj = new Person(123, 123)
   console.log(obj, '泛型')
}


